#include "ArmyState.h"
#include "UserAPI.h"
#include "BasicAI.h"
#include "params.h"

using namespace ArmyStateNS;

void DefensiveBattleState::execute()
{
	BasicAI *ai = BasicAI::instance();
	UserAPI &api = ai->get_api();
	Army *army = api.GetCntArmy();
	
	if (!api.InDanger(m_target))
	{
		BaseState *next_state = new IdleState(m_name);
		switch (api.get_my_army(m_name)->soldierType) {
		case (SOLDIER_INFANTRY):
		case (SOLDIER_RANGER):
			enter_state(m_name, new ManageState(m_name, m_target));
			return;
		case (SOLDIER_CAVALRY):
			//	TODO	complete transition
			enter_state(m_name, new IdleState(m_name));
			return;
		}
		return;
	}

	vector<Army*> op_troop = api.get_op_army_around(m_target);
	vector<Army*> my_troop = api.get_my_army_around(m_target);

	int op_army_count = 0;
	int my_army_count = 0;
	for (int i = 0; i < (int) op_troop.size(); ++i) op_army_count += op_troop[i]->numSoldier;
	for (int i = 0; i < (int) my_troop.size(); ++i) my_army_count += my_troop[i]->numSoldier;

	if (op_army_count <= my_army_count * 0.8)
	{
		//	go to fuck them
	} else
	{
		bool hasRanges = false;
		bool hasCloses = false;
		bool hasEntered = false;
		for (int i = 0; i < (int) op_troop.size(); ++i) 
		{
			if (api.GetCity(op_troop[i]->pos) == api.GetCity(m_target))
				hasEntered = true;

			if (op_troop[i]->soldierType == SOLDIER_RANGER)
				hasRanges = true;
			else
				hasCloses = true;
		}

		int ranger_count = 0;
		int closer_count = 0;
		for (int i = 0; i < (int) my_troop.size(); ++i) 
		{
			if (my_troop[i]->soldierType == SOLDIER_RANGER)
				ranger_count += my_troop[i]->numSoldier;
			else
				closer_count += my_troop[i]->numSoldier;
		}

		if (!hasRanges)
		{
			if (op_army_count > 1.5 * my_army_count || ranger_count >= (ranger_count + closer_count) * 0.4)
			{
				//	don't get out, then stay in the city and play with them
				if (api.GetCity(army->pos) != api.GetCity(m_target))
					api.Move(ai->get_action_queue(), army->pos, m_target);

				if (op_army_count > army->numSoldier * 1.5)	//	then build defense
					api.RepairCity(ai->get_action_queue(), api.GetCity(m_target), 1);

				if (api.GetCity(m_target)->hasBarrack)
					api.Recruit(ai->get_action_queue());

				for (int i = 0; i < (int) op_troop.size(); ++i) 
				{
					if (api.HamDistance(op_troop[i]->pos, army->pos) <= SOLDIER_ATTACK_RANGE[army->soldierType])
					{
						api.AttackArmy(ai->get_action_queue(), army->pos, op_troop[i]);
						break;
					}
				}
			} else if (api.GetCity(m_target)->hasBarrack) {
				//	TODO	try to put off the battle
			} else
			{
				//	TODO	withdraw
			}
		} else
		{
			//	we have to get out to attack
			if (op_army_count > my_army_count)
			{
				//	TODO	withdraw
			} else
			{
				//	go to fight!!
				if (api.GetCity(m_target)->hasBarrack)
					api.Recruit(ai->get_action_queue());

				for (int i = 0; i < (int) op_troop.size(); ++i) 
				{
					if (api.HamDistance(op_troop[i]->pos, army->pos) <= 8)
					{
						api.AttackArmy(ai->get_action_queue(), army->pos, op_troop[i]);
						break;
					}
				}
			}
		}
	}
}